package com.db.williamchart.view;

import com.db.williamchart.ChartContract;
import com.db.williamchart.animation.ChartAnimation;
import com.db.williamchart.animation.DefaultDonutAnimation;
import com.db.williamchart.animation.DonutNoAnimation;
import com.db.williamchart.data.DonutDataPoint;
import com.db.williamchart.data.Frame;
import com.db.williamchart.data.Paddings;
import com.db.williamchart.data.configuration.DonutChartConfiguration;
import com.db.williamchart.extensions.AttrUtils;
import com.db.williamchart.renderer.DonutChartRenderer;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.render.Arc;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.app.Context;

import java.util.Collections;
import java.util.List;

public class DonutChartView extends ComponentContainer implements ChartContract.DonutView {
    private static final Float defaultThickness = 50f;
    private static final int defaultColor = Color.BLACK.getValue();
    private static final int defaultBackgroundColor = Color.TRANSPARENT.getValue();
    private static final Float defaultStartAngle = 90f;
    private static final Float defaultDonutTotal = 100f;
    private List<Float> editModeSampleData = Collections.singletonList(70f);

    private float donutThickness = defaultThickness;

    private int[] donutColors = new int[]{defaultColor};

    private int donutBackgroundColor = defaultBackgroundColor;

    private boolean donutRoundCorners = false;

    private float donutTotal = defaultDonutTotal;

    private ChartAnimation<DonutDataPoint> animation = new DefaultDonutAnimation();

    private Canvas canvas;

    private ChartContract.DonutRenderer renderer = new DonutChartRenderer(this,new DonutNoAnimation());

    private Paint paint = new Paint();

    private DonutChartConfiguration chartConfiguration;

    public DonutChartView(Context context) {
        this(context,null);
    }

    public DonutChartView(Context context, AttrSet attrSet) {
        this(context, attrSet,null);
    }

    public DonutChartView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init(attrSet);
    }

    private boolean isPreDraw = false;
    private void init(AttrSet attrSet){
        donutThickness = (float) AttrUtils.getDimensionFromAttr(attrSet,"chart_donutThickness",(int) donutThickness);
        donutBackgroundColor = AttrUtils.getColorFromAttr(attrSet,"chart_donutBackgroundColor",donutBackgroundColor);
        donutRoundCorners = AttrUtils.getBooleanFromAttr(attrSet,"chart_donutRoundCorners",donutRoundCorners);
        donutTotal = AttrUtils.getFloatFromAttr(attrSet,"chart_donutTotal",donutTotal);

        addDrawTask(new DrawTask() {
            @Override
            public void onDraw(Component component, Canvas canvas) {
                DonutChartView.this.canvas = canvas;
                if (renderer != null){
                    if (!isPreDraw){
                        isPreDraw = renderer.preDraw(getChartConfiguration());
                    }
                    renderer.draw();
                }

            }
        });
    }
//    private void handleEditMode() {
//        if (isInEditMode) {
//            show(editModeSampleData);
//        }
//    }
    @Override
    public void postInvalidate() {
        invalidate();
    }

    @Override
    public void drawArc(List<Float> degrees, Frame innerFrame) {
        if (donutRoundCorners){
            paint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
        }
        paint.setStyle(Paint.Style.STROKE_STYLE);
        paint.setStrokeWidth(donutThickness);

        int index = 0;
        for (Float f : degrees){
            paint.setColor(new Color(donutColors[index]));
            canvas.drawArc(innerFrame.toRectFloat(),new Arc(defaultStartAngle,f,false),paint);
            index++;
        }
    }

    @Override
    public void drawBackground(Frame innerFrame) {
        paint.setStyle(Paint.Style.STROKE_STYLE);
        paint.setStrokeWidth(donutThickness);
        paint.setColor(new Color(donutBackgroundColor));

        float radius = (innerFrame.getBottom() - innerFrame.getTop()) / 2;
        canvas.drawCircle(
                innerFrame.getLeft() + radius,
                innerFrame.getTop() + radius,
                radius,
                paint
        );
    }

    @Override
    public void drawDebugFrame(Frame innerFrame) {
        canvas.drawRect(innerFrame.toRectFloat(), paint);
    }

    public void show(List<Float> values) {
//        addDrawTask(new DrawTask() {
//            @Override
//            public void onDraw(Component component, Canvas canvas) {
//
//            }
//        },DrawTask.BETWEEN_BACKGROUND_AND_CONTENT);
        renderer.render(values);
    }

    public void animate(List<Float> values) {
//        addDrawTask(new DrawTask() {
//            @Override
//            public void onDraw(Component component, Canvas canvas) {
//                renderer.preDraw(getChartConfiguration());
//            }
//        },DrawTask.BETWEEN_BACKGROUND_AND_CONTENT);
        renderer.anim(values, animation);
    }
    private DonutChartConfiguration getChartConfiguration(){
        if (chartConfiguration == null){
            chartConfiguration = new DonutChartConfiguration(
                    getWidth(),
                    getHeight(),
                    new Paddings(
                            getPaddingLeft(),
                            getPaddingTop(),
                            getPaddingRight(),
                            getPaddingBottom()
                    ),
                    donutThickness,
                    donutTotal,
                    donutColors.length,
                    donutBackgroundColor
            );
        }
        return chartConfiguration;
    }

    public void setDonutColors(int[] donutColors) {
        this.donutColors = donutColors;
    }

    public void setAnimationDuration(long duration){
        if (animation != null){
            animation.setDuration(duration);
        }
    }

    public void setDonutThickness(float donutThickness) {
        this.donutThickness = donutThickness;
    }

    public void setDonutBackgroundColor(int donutBackgroundColor) {
        this.donutBackgroundColor = donutBackgroundColor;
    }

    public void setDonutRoundCorners(boolean donutRoundCorners) {
        this.donutRoundCorners = donutRoundCorners;
    }

    public void setDonutTotal(float donutTotal) {
        this.donutTotal = donutTotal;
    }

    public void setAnimation(ChartAnimation<DonutDataPoint> animation) {
        this.animation = animation;
    }
}
